#include "thread_pool.h"
#include <stdlib.h>
#include <string.h>

// 创建一个任务队列，并初始化相关字段
TaskQueue *task_queue_create(int capacity) {
    // 为任务队列分配内存
    TaskQueue *queue = (TaskQueue *)malloc(sizeof(TaskQueue));
    
    // 为任务数组分配内存
    queue->tasks = (Task *)malloc(sizeof(Task) * capacity);
    
    // 初始化队列的容量、大小、头尾指针
    queue->capacity = capacity;
    queue->size = 0;
    queue->head = 0;
    queue->tail = 0;
    
    // 初始化互斥锁和条件变量
    pthread_mutex_init(&queue->lock, NULL);
    pthread_cond_init(&queue->not_empty, NULL);
    pthread_cond_init(&queue->not_full, NULL);
    
    // 返回创建的队列
    return queue;
}

// 销毁任务队列，释放相关资源
void task_queue_destroy(TaskQueue *queue) {
    // 释放任务数组内存
    free(queue->tasks);
    
    // 销毁互斥锁和条件变量
    pthread_mutex_destroy(&queue->lock);
    pthread_cond_destroy(&queue->not_empty);
    pthread_cond_destroy(&queue->not_full);
    
    // 释放队列结构体内存
    free(queue);
}

// 向任务队列中添加任务
int task_queue_push(TaskQueue *queue, Task task) {
    // 获取互斥锁，确保线程安全
    pthread_mutex_lock(&queue->lock);
    
    // 如果队列已满，等待队列有空余位置
    while (queue->size == queue->capacity) {
        pthread_cond_wait(&queue->not_full, &queue->lock);
    }
    
    // 将任务添加到队列尾部
    queue->tasks[queue->tail] = task;
    
    // 更新队列尾部指针，采用环形队列的方式
    queue->tail = (queue->tail + 1) % queue->capacity;
    
    // 增加队列大小
    queue->size++;
    
    // 通知可能在等待任务的线程队列不为空
    pthread_cond_signal(&queue->not_empty);
    
    // 释放互斥锁
    pthread_mutex_unlock(&queue->lock);
    
    return 0;
}

// 从任务队列中获取任务
int task_queue_pop(TaskQueue *queue, Task *task) {
    // 获取互斥锁，确保线程安全
    pthread_mutex_lock(&queue->lock);
    
    // 如果队列为空，等待队列中有任务
    while (queue->size == 0) {
        pthread_cond_wait(&queue->not_empty, &queue->lock);
    }
    
    // 从队列头部取出任务
    *task = queue->tasks[queue->head];
    
    // 更新队列头部指针，采用环形队列的方式
    queue->head = (queue->head + 1) % queue->capacity;
    
    // 减少队列大小
    queue->size--;
    
    // 通知可能在等待队列有空余位置的线程
    pthread_cond_signal(&queue->not_full);
    
    // 释放互斥锁
    pthread_mutex_unlock(&queue->lock);
    
    return 0;
}
